import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

class ChannelDemo {
    constructor() {
        this.scene = null;
        this.camera = null;
        this.renderer = null;
        this.controls = null;
        this.currentChannel = 'diffuse';
        
        // 几何体和材质
        this.geometry = null;
        this.material = null;
        this.mesh = null;
        
        // 光源
        this.lights = {
            ambient: null,
            directional: null,
            point: null
        };
        
        // 纹理
        this.textures = {
            diffuse: null,
            normal: null,
            roughness: null,
            metalness: null,
            emission: null,
            displacement: null,
            occlusion: null
        };
        
        // 材质参数
        this.materialParams = {
            color: 0xffffff,
            roughness: 0.5,
            metalness: 0.0,
            normalScale: 1.0,
            emissiveIntensity: 0.0,
            displacementScale: 0.1,
            aoMapIntensity: 1.0
        };
        
        this.init();
        this.setupEventListeners();
        this.animate();
    }
    
    init() {
        // 创建场景
        this.scene = new THREE.Scene();
        this.scene.background = new THREE.Color(0x2c3e50);
        
        // 创建相机
        this.camera = new THREE.PerspectiveCamera(
            75,
            window.innerWidth / window.innerHeight,
            0.1,
            1000
        );
        this.camera.position.set(0, 0, 5);
        
        // 创建渲染器
        this.renderer = new THREE.WebGLRenderer({ antialias: true });
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.renderer.shadowMap.enabled = true;
        this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
        this.renderer.toneMappingExposure = 1.0;
        
        const container = document.getElementById('scene-container');
        container.appendChild(this.renderer.domElement);
        
        // 创建控制器
        this.controls = new OrbitControls(this.camera, this.renderer.domElement);
        this.controls.enableDamping = true;
        this.controls.dampingFactor = 0.05;
        
        // 创建光源
        this.createLights();
        
        // 创建纹理
        this.createTextures();
        
        // 创建几何体和材质
        this.createGeometry();
        
        // 设置初始通道
        this.switchChannel('diffuse');
        
        // 处理窗口大小变化
        window.addEventListener('resize', () => this.onWindowResize());
    }
    
    createLights() {
        // 环境光
        this.lights.ambient = new THREE.AmbientLight(0x404040, 0.3);
        this.scene.add(this.lights.ambient);
        
        // 方向光
        this.lights.directional = new THREE.DirectionalLight(0xffffff, 1.0);
        this.lights.directional.position.set(5, 5, 5);
        this.lights.directional.castShadow = true;
        this.lights.directional.shadow.mapSize.setScalar(2048);
        this.lights.directional.shadow.camera.near = 0.1;
        this.lights.directional.shadow.camera.far = 50;
        this.lights.directional.shadow.camera.left = -10;
        this.lights.directional.shadow.camera.right = 10;
        this.lights.directional.shadow.camera.top = 10;
        this.lights.directional.shadow.camera.bottom = -10;
        this.scene.add(this.lights.directional);
        
        // 点光源
        this.lights.point = new THREE.PointLight(0xff6b6b, 0.5, 10);
        this.lights.point.position.set(-3, 2, 3);
        this.scene.add(this.lights.point);
    }
    
    createTextures() {
        const loader = new THREE.TextureLoader();
        
        // 创建程序化纹理
        this.textures.diffuse = this.createDiffuseTexture();
        this.textures.normal = this.createNormalTexture();
        this.textures.roughness = this.createRoughnessTexture();
        this.textures.metalness = this.createMetalnessTexture();
        this.textures.emission = this.createEmissionTexture();
        this.textures.displacement = this.createDisplacementTexture();
        this.textures.occlusion = this.createOcclusionTexture();
    }
    
    createDiffuseTexture() {
        const canvas = document.createElement('canvas');
        canvas.width = 512;
        canvas.height = 512;
        const ctx = canvas.getContext('2d');
        
        // 创建棋盘格纹理
        const tileSize = 64;
        for (let x = 0; x < canvas.width; x += tileSize) {
            for (let y = 0; y < canvas.height; y += tileSize) {
                const isEven = ((x / tileSize) + (y / tileSize)) % 2 === 0;
                ctx.fillStyle = isEven ? '#ff6b6b' : '#4ecdc4';
                ctx.fillRect(x, y, tileSize, tileSize);
            }
        }
        
        const texture = new THREE.CanvasTexture(canvas);
        texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
        texture.repeat.set(2, 2);
        return texture;
    }
    
    createNormalTexture() {
        const canvas = document.createElement('canvas');
        canvas.width = 512;
        canvas.height = 512;
        const ctx = canvas.getContext('2d');
        
        // 创建法线贴图（蓝紫色调）
        const imageData = ctx.createImageData(canvas.width, canvas.height);
        for (let i = 0; i < imageData.data.length; i += 4) {
            const x = (i / 4) % canvas.width;
            const y = Math.floor((i / 4) / canvas.width);
            
            // 创建波浪法线
            const nx = Math.sin(x * 0.02) * 0.5 + 0.5;
            const ny = Math.sin(y * 0.02) * 0.5 + 0.5;
            const nz = 1.0;
            
            imageData.data[i] = nx * 255;     // R
            imageData.data[i + 1] = ny * 255; // G
            imageData.data[i + 2] = nz * 255; // B
            imageData.data[i + 3] = 255;      // A
        }
        
        ctx.putImageData(imageData, 0, 0);
        
        const texture = new THREE.CanvasTexture(canvas);
        texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
        texture.repeat.set(2, 2);
        return texture;
    }
    
    createRoughnessTexture() {
        const canvas = document.createElement('canvas');
        canvas.width = 512;
        canvas.height = 512;
        const ctx = canvas.getContext('2d');
        
        // 创建粗糙度渐变
        const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
        gradient.addColorStop(0, '#000000'); // 光滑
        gradient.addColorStop(1, '#ffffff'); // 粗糙
        
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        const texture = new THREE.CanvasTexture(canvas);
        texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
        texture.repeat.set(2, 2);
        return texture;
    }
    
    createMetalnessTexture() {
        const canvas = document.createElement('canvas');
        canvas.width = 512;
        canvas.height = 512;
        const ctx = canvas.getContext('2d');
        
        // 创建金属度条纹
        for (let y = 0; y < canvas.height; y += 32) {
            const isMetal = (y / 32) % 2 === 0;
            ctx.fillStyle = isMetal ? '#ffffff' : '#000000';
            ctx.fillRect(0, y, canvas.width, 32);
        }
        
        const texture = new THREE.CanvasTexture(canvas);
        texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
        texture.repeat.set(2, 2);
        return texture;
    }
    
    createEmissionTexture() {
        const canvas = document.createElement('canvas');
        canvas.width = 512;
        canvas.height = 512;
        const ctx = canvas.getContext('2d');
        
        // 创建发光点
        ctx.fillStyle = '#000000';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        ctx.fillStyle = '#ffff00';
        for (let i = 0; i < 20; i++) {
            const x = Math.random() * canvas.width;
            const y = Math.random() * canvas.height;
            const radius = Math.random() * 20 + 5;
            
            const gradient = ctx.createRadialGradient(x, y, 0, x, y, radius);
            gradient.addColorStop(0, '#ffff00');
            gradient.addColorStop(1, '#000000');
            
            ctx.fillStyle = gradient;
            ctx.beginPath();
            ctx.arc(x, y, radius, 0, Math.PI * 2);
            ctx.fill();
        }
        
        const texture = new THREE.CanvasTexture(canvas);
        texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
        texture.repeat.set(2, 2);
        return texture;
    }
    
    createDisplacementTexture() {
        const canvas = document.createElement('canvas');
        canvas.width = 512;
        canvas.height = 512;
        const ctx = canvas.getContext('2d');
        
        // 创建高度图
        const imageData = ctx.createImageData(canvas.width, canvas.height);
        for (let i = 0; i < imageData.data.length; i += 4) {
            const x = (i / 4) % canvas.width;
            const y = Math.floor((i / 4) / canvas.width);
            
            const height = (Math.sin(x * 0.01) + Math.sin(y * 0.01)) * 0.5 + 0.5;
            const value = height * 255;
            
            imageData.data[i] = value;     // R
            imageData.data[i + 1] = value; // G
            imageData.data[i + 2] = value; // B
            imageData.data[i + 3] = 255;   // A
        }
        
        ctx.putImageData(imageData, 0, 0);
        
        const texture = new THREE.CanvasTexture(canvas);
        texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
        texture.repeat.set(2, 2);
        return texture;
    }
    
    createOcclusionTexture() {
        const canvas = document.createElement('canvas');
        canvas.width = 512;
        canvas.height = 512;
        const ctx = canvas.getContext('2d');
        
        // 创建环境遮蔽
        const gradient = ctx.createRadialGradient(
            canvas.width / 2, canvas.height / 2, 0,
            canvas.width / 2, canvas.height / 2, canvas.width / 2
        );
        gradient.addColorStop(0, '#ffffff');
        gradient.addColorStop(1, '#000000');
        
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        const texture = new THREE.CanvasTexture(canvas);
        texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
        texture.repeat.set(2, 2);
        return texture;
    }
    
    createGeometry() {
        // 创建球体几何体
        this.geometry = new THREE.SphereGeometry(1.5, 64, 64);
        
        // 创建PBR材质
        this.material = new THREE.MeshStandardMaterial({
            color: this.materialParams.color,
            roughness: this.materialParams.roughness,
            metalness: this.materialParams.metalness
        });
        
        // 创建网格
        this.mesh = new THREE.Mesh(this.geometry, this.material);
        this.mesh.castShadow = true;
        this.mesh.receiveShadow = true;
        this.scene.add(this.mesh);
        
        // 添加地面
        const groundGeometry = new THREE.PlaneGeometry(20, 20);
        const groundMaterial = new THREE.MeshStandardMaterial({ 
            color: 0x808080,
            roughness: 0.8,
            metalness: 0.1
        });
        const ground = new THREE.Mesh(groundGeometry, groundMaterial);
        ground.rotation.x = -Math.PI / 2;
        ground.position.y = -2;
        ground.receiveShadow = true;
        this.scene.add(ground);
    }
    
    switchChannel(channelType) {
        this.currentChannel = channelType;
        
        // 重置材质
        this.material.map = null;
        this.material.normalMap = null;
        this.material.roughnessMap = null;
        this.material.metalnessMap = null;
        this.material.emissiveMap = null;
        this.material.displacementMap = null;
        this.material.aoMap = null;
        
        // 重置材质属性
        this.material.color.setHex(this.materialParams.color);
        this.material.roughness = this.materialParams.roughness;
        this.material.metalness = this.materialParams.metalness;
        this.material.normalScale.set(this.materialParams.normalScale, this.materialParams.normalScale);
        this.material.emissive.setHex(0x000000);
        this.material.emissiveIntensity = this.materialParams.emissiveIntensity;
        this.material.displacementScale = this.materialParams.displacementScale;
        this.material.aoMapIntensity = this.materialParams.aoMapIntensity;
        
        // 根据通道类型设置相应的贴图
        switch (channelType) {
            case 'diffuse':
                this.material.map = this.textures.diffuse;
                break;
            case 'normal':
                this.material.normalMap = this.textures.normal;
                this.material.normalScale.set(2.0, 2.0);
                break;
            case 'roughness':
                this.material.roughnessMap = this.textures.roughness;
                break;
            case 'metalness':
                this.material.metalnessMap = this.textures.metalness;
                break;
            case 'emission':
                this.material.emissiveMap = this.textures.emission;
                this.material.emissive.setHex(0xffffff);
                this.material.emissiveIntensity = 1.0;
                break;
            case 'displacement':
                this.material.displacementMap = this.textures.displacement;
                this.material.displacementScale = 0.3;
                break;
            case 'occlusion':
                this.material.aoMap = this.textures.occlusion;
                this.material.aoMapIntensity = 1.5;
                break;
        }
        
        this.material.needsUpdate = true;
        
        // 更新UI
        this.updateChannelButtons();
        this.updateChannelInfo();
    }
    
    updateChannelButtons() {
        const buttons = document.querySelectorAll('.channel-btn');
        buttons.forEach(btn => {
            btn.classList.remove('active');
            if (btn.dataset.channel === this.currentChannel) {
                btn.classList.add('active');
            }
        });
    }
    
    updateChannelInfo() {
        const details = document.querySelectorAll('.channel-detail');
        details.forEach(detail => {
            detail.classList.remove('active');
            if (detail.dataset.channel === this.currentChannel) {
                detail.classList.add('active');
            }
        });
    }
    
    updateMaterialParams() {
        // 更新材质参数
        this.material.color.setHex(parseInt(document.getElementById('color').value.replace('#', '0x')));
        this.material.roughness = parseFloat(document.getElementById('roughness').value);
        this.material.metalness = parseFloat(document.getElementById('metalness').value);
        this.material.normalScale.set(
            parseFloat(document.getElementById('normalScale').value),
            parseFloat(document.getElementById('normalScale').value)
        );
        this.material.emissiveIntensity = parseFloat(document.getElementById('emissiveIntensity').value);
        this.material.displacementScale = parseFloat(document.getElementById('displacementScale').value);
        this.material.aoMapIntensity = parseFloat(document.getElementById('aoMapIntensity').value);
        
        // 更新显示值
        document.getElementById('roughnessValue').textContent = this.material.roughness.toFixed(2);
        document.getElementById('metalnessValue').textContent = this.material.metalness.toFixed(2);
        document.getElementById('normalScaleValue').textContent = parseFloat(document.getElementById('normalScale').value).toFixed(1);
        document.getElementById('emissiveIntensityValue').textContent = this.material.emissiveIntensity.toFixed(1);
        document.getElementById('displacementScaleValue').textContent = this.material.displacementScale.toFixed(2);
        document.getElementById('aoMapIntensityValue').textContent = this.material.aoMapIntensity.toFixed(1);
    }
    
    updateLights() {
        // 更新光源参数
        this.lights.ambient.intensity = parseFloat(document.getElementById('ambientIntensity').value);
        this.lights.directional.intensity = parseFloat(document.getElementById('directionalIntensity').value);
        this.lights.point.intensity = parseFloat(document.getElementById('pointIntensity').value);
        
        // 更新显示值
        document.getElementById('ambientIntensityValue').textContent = this.lights.ambient.intensity.toFixed(1);
        document.getElementById('directionalIntensityValue').textContent = this.lights.directional.intensity.toFixed(1);
        document.getElementById('pointIntensityValue').textContent = this.lights.point.intensity.toFixed(1);
    }
    
    setupEventListeners() {
        // 通道切换按钮
        const channelButtons = document.querySelectorAll('.channel-btn');
        channelButtons.forEach(btn => {
            btn.addEventListener('click', () => {
                this.switchChannel(btn.dataset.channel);
            });
        });
        
        // 材质参数控制
        const materialControls = ['color', 'roughness', 'metalness', 'normalScale', 'emissiveIntensity', 'displacementScale', 'aoMapIntensity'];
        materialControls.forEach(control => {
            const element = document.getElementById(control);
            if (element) {
                element.addEventListener('input', () => this.updateMaterialParams());
            }
        });
        
        // 光源控制
        const lightControls = ['ambientIntensity', 'directionalIntensity', 'pointIntensity'];
        lightControls.forEach(control => {
            const element = document.getElementById(control);
            if (element) {
                element.addEventListener('input', () => this.updateLights());
            }
        });
        
        // 重置按钮
        document.getElementById('resetBtn').addEventListener('click', () => {
            this.resetToDefaults();
        });
    }
    
    resetToDefaults() {
        // 重置材质参数
        document.getElementById('color').value = '#ffffff';
        document.getElementById('roughness').value = '0.5';
        document.getElementById('metalness').value = '0.0';
        document.getElementById('normalScale').value = '1.0';
        document.getElementById('emissiveIntensity').value = '0.0';
        document.getElementById('displacementScale').value = '0.1';
        document.getElementById('aoMapIntensity').value = '1.0';
        
        // 重置光源参数
        document.getElementById('ambientIntensity').value = '0.3';
        document.getElementById('directionalIntensity').value = '1.0';
        document.getElementById('pointIntensity').value = '0.5';
        
        // 更新材质和光源
        this.updateMaterialParams();
        this.updateLights();
        
        // 重新应用当前通道
        this.switchChannel(this.currentChannel);
    }
    
    onWindowResize() {
        const container = document.getElementById('scene-container');
        const width = container.clientWidth;
        const height = container.clientHeight;
        
        this.camera.aspect = width / height;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(width, height);
    }
    
    animate() {
        requestAnimationFrame(() => this.animate());
        
        // 旋转物体
        if (this.mesh) {
            this.mesh.rotation.y += 0.005;
        }
        
        // 更新控制器
        this.controls.update();
        
        // 渲染场景
        this.renderer.render(this.scene, this.camera);
    }
}

// 初始化应用
window.addEventListener('DOMContentLoaded', () => {
    new ChannelDemo();
});